<template>
  <div class="image-upload-container">
    <el-upload
      :class="['image-uploader', uploadClass]"
      action="#"
      :auto-upload="false"
      :show-file-list="!isSingle"
      :on-change="handleChange"
      :on-remove="handleRemove"
      :accept="accept"
      :multiple="!isSingle"
      :limit="limit"
      :list-type="listType"
      :drag="drag"
    >
      <!-- 单图上传预览 -->
      <template v-if="isSingle">
        <img v-if="previewUrl" :src="previewUrl" :class="previewClass" :style="previewStyle" />
        <div v-else :class="iconWrapperClass" :style="iconWrapperStyle">
          <el-icon :class="iconClass">
            <Plus />
          </el-icon>
          <div v-if="showTip" class="upload-tip">{{ tipText }}</div>
        </div>
      </template>

      <!-- 多图上传图标 -->
      <template v-else>
        <el-icon :class="iconClass">
          <Plus />
        </el-icon>
      </template>
    </el-upload>

    <!-- 提示文字 -->
    <div v-if="showHint" class="upload-hint">
      {{ hintText }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue"
import type { StyleValue } from "vue"
import { ElMessage } from "element-plus"
import { Plus } from "@element-plus/icons-vue"
import type { UploadFile } from "element-plus"

interface Props {
  /** 是否单图上传，默认 true */
  isSingle?: boolean
  /** 上传文件列表上限，默认 1（单图）或 10（多图）*/
  limit?: number
  /** 最大文件大小（MB），默认 2MB */
  maxSize?: number
  /** 接受的文件类型，默认 image/jpeg,image/png,image/jpg */
  accept?: string
  /** 是否拖拽上传，默认 false */
  drag?: boolean
  /** 列表类型，默认 picture-card */
  listType?: "text" | "picture" | "picture-card"
  /** 预览图片的 class */
  previewClass?: string
  /** 预览图片的 style */
  previewStyle?: StyleValue
  /** 上传区域的 class */
  uploadClass?: string
  /** 图标容器的 class */
  iconWrapperClass?: string
  /** 图标容器的 style */
  iconWrapperStyle?: StyleValue
  /** 图标的 class */
  iconClass?: string
  /** 是否显示点击区域内的提示文字 */
  showTip?: boolean
  /** 点击区域内的提示文字 */
  tipText?: string
  /** 是否显示底部提示 */
  showHint?: boolean
  /** 底部提示文字 */
  hintText?: string
  /** 初始图片 URL（单图模式） */
  initialUrl?: string
  /** v-model 绑定的值（单图返回 File，多图返回 File[]）*/
  modelValue?: File | File[] | null
}

const props = withDefaults(defineProps<Props>(), {
  isSingle: true,
  limit: undefined,
  maxSize: 2,
  accept: "image/jpeg,image/png,image/jpg",
  drag: false,
  listType: "picture-card",
  previewClass: "preview-image",
  previewStyle: undefined,
  uploadClass: "",
  iconWrapperClass: "icon-wrapper",
  iconWrapperStyle: undefined,
  iconClass: "upload-icon",
  showTip: false,
  tipText: "点击上传",
  showHint: true,
  hintText: "",
  initialUrl: "",
  modelValue: null
})

const emit = defineEmits<{
  (e: "update:modelValue", value: File | File[] | null): void
  (e: "change", value: File | File[]): void
  (e: "preview", url: string): void
}>()

// 预览 URL（单图模式）
const previewUrl = ref<string>(props.initialUrl || "")

// 文件列表（多图模式）
const fileList = ref<File[]>([])

// 计算实际的上传限制
const actualLimit = computed(() => {
  if (props.limit !== undefined) return props.limit
  return props.isSingle ? 1 : 10
})

// 计算提示文字
const computedHintText = computed(() => {
  if (props.hintText) return props.hintText

  const types = props.accept.split(",").map(t => t.split("/")[1]?.toUpperCase()).join("/")
  const sizeText = `大小不超过 ${props.maxSize}MB`

  if (props.isSingle) {
    return `支持 ${types} 格式，${sizeText}`
  } else {
    return `支持 ${types} 格式，${sizeText}，最多上传 ${actualLimit.value} 张`
  }
})

// 监听初始URL变化
watch(() => props.initialUrl, (newUrl) => {
  previewUrl.value = newUrl || ""
})

// 处理文件上传
const handleChange = (file: UploadFile) => {
  // 文件类型验证
  const acceptTypes = props.accept.split(",")
  const isValidType = acceptTypes.some(type => file.raw?.type === type.trim())

  if (!isValidType) {
    const typeNames = acceptTypes.map(t => t.split("/")[1]?.toUpperCase()).join("/")
    ElMessage.error(`只支持 ${typeNames} 格式的图片！`)
    return
  }

  // 文件大小验证
  const isValidSize = (file.raw?.size || 0) / 1024 / 1024 < props.maxSize
  if (!isValidSize) {
    ElMessage.error(`图片大小不能超过 ${props.maxSize}MB！`)
    return
  }

  if (props.isSingle) {
    // 单图模式
    const rawFile = file.raw as File
    previewUrl.value = URL.createObjectURL(rawFile)
    emit("update:modelValue", rawFile)
    emit("change", rawFile)
    emit("preview", previewUrl.value)
  } else {
    // 多图模式
    const rawFile = file.raw as File
    fileList.value.push(rawFile)
    emit("update:modelValue", [...fileList.value])
    emit("change", [...fileList.value])
  }
}

// 处理文件移除（多图模式）
const handleRemove = (file: UploadFile) => {
  const index = fileList.value.findIndex(f => f.name === file.name)
  if (index > -1) {
    fileList.value.splice(index, 1)
    emit("update:modelValue", [...fileList.value])
    emit("change", [...fileList.value])
  }
}

// 清空上传
const clear = () => {
  if (props.isSingle) {
    previewUrl.value = ""
    emit("update:modelValue", null)
  } else {
    fileList.value = []
    emit("update:modelValue", [])
  }
}

// 获取文件
const getFile = () => {
  return props.isSingle ? (previewUrl.value ? props.modelValue : null) : fileList.value
}

// 暴露方法
defineExpose({
  clear,
  getFile
})
</script>

<style scoped lang="scss">
.image-upload-container {
  display: inline-block;

  .image-uploader {
    :deep(.el-upload) {
      border: 2px dashed #d9d9d9;
      border-radius: 8px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      transition: all 0.3s;

      &:hover {
        border-color: #667eea;
      }
    }

    &.single-avatar {
      :deep(.el-upload) {
        width: 120px;
        height: 120px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }

    &.large-avatar {
      :deep(.el-upload) {
        width: 178px;
        height: 178px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }

  .preview-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }

  .icon-wrapper {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .upload-icon {
    font-size: 32px;
    color: #8c939d;
  }

  .upload-tip {
    margin-top: 8px;
    font-size: 12px;
    color: #8c939d;
  }

  .upload-hint {
    margin-top: 8px;
    font-size: 12px;
    color: #999;
    line-height: 1.5;
  }
}

// 拖拽上传样式
:deep(.el-upload-dragger) {
  padding: 20px;

  .el-icon {
    font-size: 67px;
    color: #c0c4cc;
    margin-bottom: 16px;
  }

  .el-upload__text {
    color: #606266;
    font-size: 14px;

    em {
      color: #667eea;
      font-style: normal;
    }
  }
}
</style>

